/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.txweb.support;

import com.jspx.boot.environment.Environment;
import com.jspx.boot.sign.SafetyLevel;
import com.jspx.boot.sign.UserType;
import com.jspx.boot.sign.YesNoType;
import com.jspx.json.JSONArray;
import com.jspx.json.JSONException;
import com.jspx.json.JSONObject;
import com.jspx.scriptmark.util.ScriptConverter;
import com.jspx.security.utils.EncryptUtil;
import com.jspx.txweb.*;
import com.jspx.txweb.Option;
import com.jspx.txweb.annotation.Safety;
import com.jspx.txweb.dispatcher.Dispatcher;
import com.jspx.txweb.env.TXWeb;
import com.jspx.txweb.table.ActionLog;
import com.jspx.txweb.table.Role;
import com.jspx.txweb.table.UserSession;
import com.jspx.txweb.util.RequestUtil;
import com.jspx.txweb.util.TXWebUtil;
import com.jspx.utils.*;
import com.jspx.txweb.bundle.Bundle;
import com.jspx.sioc.annotation.Ref;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.Serializable;
import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User:chenYuan (mail:39793751@qq.com)
 * Date: 2006-12-26
 * Time: 17:23:13
 * InterceptorSupport
 */
public abstract class ActionSupport implements Action {

    static public final String KEY_RETURN = "return"; //返回不运行下边的程序
    static public final String SUCCESS = "success"; //无问题

    //返回---begin
    static public final String NONE = "none"; //什么也不处理 并且不会调用 Redirect

    static public final String ERROR = "error"; //发生错误

    static public final String INPUT = "input"; //录入不完整

    static public final String FAIL = "fail"; //操作失败

    static public final String LOGIN = "login"; //跳转到登录
    static public final String PASSWORD = "password"; //需要密码
    static public final String UNTITLED = "untitled";  //无权利的
    static public final String MESSAGE = "message"; //返回信息
    static public final String TEMPLATE = "template"; //返回信息  ,最基本的模板返回
    static public final String HtmlImg = "htmlImg"; //html转换为png 图片
    static public final String HtmlPdf = "htmlPdf"; //html转换为pdf文档
    static public final String Markdown = "markdown"; //html转换为pdf文档
    static public final String FileSave = "fileSave"; //将页面生成的文件保存为文件，主要提供生成静态文件使用
    static public final String PdfPageImg = "pdfPageImg"; //pdf 一页转换为图片输出

    //static public final String STEMPLATE = "stemplate"; //返回信息  ,最基本的模板返回
    static public final String LICENSE = "license"; //返回信息

    static public final String CHAIN = "chain"; //返回信息
    static public final String XSTREAM = "xstream"; //XML Bean
    static public final String QRCode = "qrcode"; //XML Bean

    static public final String ROC = "roc"; //json xml 格式的的数据对象返回
    static public final String EXCEL = "excel"; //json格式的消息
    static public final String CHARTS = "charts"; //FusionCharts 图形
    static public final String REDIRECT = "redirect"; //页面跳转
    static public final String PRINT = "print"; //页面跳转
    static public final String FORWARD = "forward"; //页面跳转

    //返回---end

    //浏览器控制 begin
    static public final String BrowserCache = "BrowserCache"; //是否使用浏览器缓存 默认为 true
    static public final String ContentType = "ContentType"; //请求类型
    static public final String Content_Disposition = "Content-Disposition"; //下载类型
    static public final String KEY_RedirectUrl = "RedirectUrl"; //注释方式的配置返回
    //浏览器控制 end

    //是否载入手机模板,如果是手机，那么载入 name.mobile.ftl 否则 name.ftl  目录不变
    static public final String KEY_MobileTemplate = "mobileTemplate";

    static public final String BOM = "bom"; //UTF-8 带BOM输出,图形报表使用

    //保存调用方法，用来判断是否发生了操作，例如发生操作后是否清空刷新缓存
    static public final String Key_CallMethodName = "callMethodName";
    static public final String Key_CallRocJsonData = "callRocDataJson";

    static public final String Key_Session = "session";
    static public final String Key_Request = "request";
    static public final String Key_Response = "response";
    static public final String Key_RealPath = "RealPath";
//    static public final String Key_Locale = "Locale";
    static public final String Key_FormHash = "formHash";
    static public final String Key_DispatcherTimes = "DispatcherTimes"; //dispatcher 访问次数 Times
    static public final String Key_ActionName = "ActionName";
    static public final String Key_This = "action";
    static public final String Key_Namespace = "Namespace";
    //static public final String Key_Template = "ActionTemplate";
    static public final String Key_Result = "ActionResult";
    static public final String Key_FieldInfo = "FieldInfo";
    static public final String Key_ActionMessages = "ActionMessages";
    static public final String Key_Config = "Config";  //配置
    static public final String Key_Language = "Language"; //语言
    static public final String Key_Option = "Option"; //字典

    static public final String Key_UserSession = "IUserSession"; //TXWeb 不做处理 留给用户自己处理
    static public final String Key_ResultMethods = "resultMethods"; //json 返回数据的方法列表
    static public final String Key_ActionLogContent = "ActionLogContent";
    static public final String Key_ActionLogTitle = "ActionLogTitle";
    static public final String Key_ActionResultObject = "ActionResultObject";
    static public final String Key_PageEnable = "pageEnable";

    static public final String mobileTemplateSuffix = "mobile"; //返回不运行下边的程序


    private String actionResult = INPUT; //返回INPUT

    final private transient Map<String, Object> environment = new HashMap<String, Object>();
    //fusionCharts 图形文字换行
    //protected static final String ChartTextWrap = "&#xD;";
    protected transient HttpSession session = null;
    protected transient HttpServletRequest request;
    protected transient HttpServletResponse response;

    public ActionSupport() {

    }


    public void initialize()  {

    }

    public void destroy() {
        for (String name : environment.keySet()) {
            if (Key_Config.equals(name) || Key_Language.equals(name) || Key_Option.equals(name) || Key_UserSession.equals(name))
                continue;
            Object o = environment.get(name);
            if (o instanceof Map) {
                ((Map) o).clear();
            } else if (o instanceof List) {
                ((List) o).clear();
            }
        }
        environment.clear();
        actionResult = INPUT;
    }

    //设置为false表示不使用模板
    protected Bundle language;
    @Safety(request = false)
    @Ref(name = Environment.language, test = true)
    public void setLanguage(Bundle language) {
        this.language = language;
    }

    protected Bundle config;
    @Safety(request = false)
    @Ref(name = Environment.config, test = true)
    public void setConfig(Bundle config) {
        this.config = config;
    }

    protected Option option;
    @Safety(request = false)
    @Ref(name = Environment.option, namespace = Environment.Global, test = true)
    public void setOption(Option option) {
        this.option = option;
    }

    //这里要放置ajax方式调用出去
    public Bundle getConfig() {
        return config;
    }

    public Bundle getLanguage() {
        return language;
    }

    public Option getOption() {
        return option;
    }

    private boolean process = true;

    public boolean isProcess() {
        return process;
    }

    public void setProcess(boolean process) {
        this.process = process;
    }

    public String getLocaleName()
    {
        return RequestUtil.getLocale(request);
    }

    public String getEncode()
    {
        return Dispatcher.getEncode();
    }

    /**
     * @return 得到应用的根目录名
     */
    public String getRootNamespace() {
        return TXWebUtil.getRootNamespace(getEnv(Key_Namespace));
    }

    /**
     * @return 得到环境空间
     */
    public Map<String, Object> getEnv() {
        return environment;
    }

    /**
     * @param key 放入环境变量
     * @param obj 放入环境对象
     */
    public void put(String key, Object obj) {
        environment.put(key, obj);
    }

    /**
     * @param key 变量名称
     * @return 判断是否存在环境变量
     */

    public boolean containsKey(String key) {
        return environment.containsKey(key);
    }


    /**
     * @param environment 放入全新的环境变量
     */
    @Safety(request = false)
    public void setEnv(Map<String, Object> environment) {
        this.environment.clear();
        this.environment.putAll(environment);
    }


    public String getEnv(String keys) {
        Object o = environment.get(keys);
        if (o == null) return StringUtil.empty;
        return o.toString();
    }

    /**
     * @return 得到用户在线信息
     */
    public Object getUserSession() {
        Object userSession = environment.get(Key_UserSession);
        if (userSession == null && session != null) {
            userSession = session.getAttribute(Key_UserSession);
        }
        if (userSession==null)
        {
            //创建一个游客账号
            userSession = new UserSession();
        }
        return userSession;
    }

    /**
     * @return 判断是否为游客
     */
    public boolean isGuest() {
        return isGuest((IUserSession) getUserSession());
    }


    private static boolean isGuest(IUserSession userSession) {
        return userSession == null || userSession.isGuest();
    }

    ////////////提交错误的时候显示的错误字段信息 begin  如果使用校验后错误信息会保存在这里边

    /**
     * @return 得到错误信息
     */
    @SuppressWarnings("unchecked")
    public Map<String, String> getFieldInfo() {
        Map<String, String> fieldErrors = (Map<String, String>) environment.get(Key_FieldInfo);
        if (fieldErrors == null) {
            fieldErrors = new HashMap<String, String>();
            environment.put(Key_FieldInfo, fieldErrors);
        }
        return fieldErrors;
    }

    /**
     * 添加提示信息或者错误错误类型
     *
     * @param keys 错误类型
     * @param msg  信息
     */
    @SuppressWarnings("unchecked")
    public void addFieldInfo(String keys, String msg) {
        Map<String, String> fieldError = (Map<String, String>) environment.get(Key_FieldInfo);
        if (fieldError == null) {
            fieldError = new HashMap<String, String>();
            environment.put(Key_FieldInfo, fieldError);
        }
        fieldError.put(keys, msg);
    }

    /**
     * @param errors 放入错误信息
     */
    @SuppressWarnings("unchecked")
    public void addFieldInfo(Map<String, String> errors) {
        Map fieldError = (Map) environment.get(Key_FieldInfo);
        if (fieldError == null) {
            fieldError = new HashMap<String, String>();
            environment.put(Key_FieldInfo, errors);
        }
        fieldError.putAll(errors);
    }

    /**
     * @return 判断是否有错误信息
     */
    @SuppressWarnings("unchecked")
    public boolean hasFieldInfo() {
        Map<String, String> fieldError = (Map<String, String>) environment.get(Key_FieldInfo);
        return fieldError != null && !fieldError.isEmpty();
    }
    ////////////提交错误的时候显示的错误字段信息 end

    ////////////信息文字说明

    /**
     * @param msg 添加说明信息
     */
    @SuppressWarnings("unchecked")
    public void addActionMessage(String msg) {
        List<String> actionMsg = (List<String>) environment.get(Key_ActionMessages);
        if (actionMsg == null) {
            actionMsg = new ArrayList<String>();
        }
        actionMsg.add(msg);
        environment.put(Key_ActionMessages, actionMsg);
    }

    /**
     * @return 说明信息列表
     */
    @SuppressWarnings("unchecked")
    public List<String> getActionMessage() {
        List<String> list = (List<String>) environment.get(Key_ActionMessages);
        if (list == null) {
            list = new ArrayList<String>();
            environment.put(Key_ActionMessages, list);
        }
        return list;
    }

    /**
     * @return 是否有说明信息
     */
    @SuppressWarnings("unchecked")
    public boolean hasActionMessage() {
        List<String> actionMsg = (List<String>) environment.get(Key_ActionMessages);
        return actionMsg != null && !actionMsg.isEmpty();
    }

    /**
     * @param value 放入日志对象
     */
    @Safety(request = false)
    public void setActionLogTitle(String value) {
        environment.put(Key_ActionLogTitle, value);
    }

    /**
     * @return 得到日志记录对象
     */
    public String getActionLogTitle() {
        return (String) environment.get(Key_ActionLogTitle);
    }

    /**
     * @param value 放入日志对象
     */
    @Safety(request = false)
    public void setActionLogContent(Serializable value) {
        environment.put(Key_ActionLogContent, value);
    }

    /**
     * @return 得到日志记录对象
     */
    public Object getActionLogContent() {
        return environment.get(Key_ActionLogContent);
    }

    /**
     * @param value 当返回为excel等需要处理的数据是，这里放入数据 对象
     */
    @Safety(request = false)
    public void setResult(Object value) {
        environment.put(Key_ActionResultObject, value);
    }

    /**
     * 这里只是提供一个保存的空间，方便返回接口统一的到一个地方取数据
     *
     * @return 返回对象
     */
    public Object getResult() {
        return environment.get(Key_ActionResultObject);
    }

    public HttpSession getSession() {
        return session;
    }

    public HttpServletRequest getRequest() {
        return request;
    }

    @Safety(request = false)
    public void setRequest(final HttpServletRequest request) {
        this.request = request;
        if (this.request != null)
            session = this.request.getSession();
    }

    public HttpServletResponse getResponse() {
        return response;
    }

    @Safety(request = false)
    public void setResponse(final HttpServletResponse response) {
        this.response = response;
    }

    private  JSONObject getJsonParams()
    {
        JSONObject json = (JSONObject)environment.get(Key_CallRocJsonData);
        JSONObject params = json.getJSONObject(Environment.rocParams);
        if (params!=null)
            return params;
        return null;
    }

    public Object getBean(Class cla) throws Exception {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
                return params.toJavaObject(cla);
        }
        return RequestUtil.getBean(request, cla,false);
    }


    public String getString(String name) {
        return getString(name, false);
    }

    public String getString(String name, boolean checkSql) {
        return getString(name,StringUtil.empty,checkSql);
    }

    public String getString(String name, String def, boolean checkSql) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                if (checkSql)
                    return TXWebUtil.getSafeFilter(params.getString(name),RequestUtil.paramMaxLength, SafetyLevel.Middle);
                return params.getString(name);
            }
        }
        return RequestUtil.getString(request, name, def, checkSql);
    }

    public int getInt(String name)  {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return params.getInt(name);
            }
        }
        return RequestUtil.getInt(request, name);
    }

    public int getInt(String name, int def) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return params.getInt(name);
            }
        }
        return RequestUtil.getInt(request, name, def);
    }

    public String[] getArray(String name, boolean checkSql) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (String[])BeanUtil.getTypeValue(params.get(name),String[].class);
            }
        }
        return RequestUtil.getArray(request, name, checkSql);
    }

    public int[] getIntArray(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (int[])BeanUtil.getTypeValue(params.get(name),int[].class);
            }
        }
        return RequestUtil.getIntArray(request, name);
    }

    public int[] getIntArray(String name,int[] defArray)
    {
        int[] ids = getIntArray(name);
        if (ArrayUtil.isEmpty(ids)) return defArray;
        return ids;
    }

    public Integer[] getIntegerArray(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (Integer[])BeanUtil.getTypeValue(params.get(name),Integer[].class);
            }
        }
        return RequestUtil.getIntegerArray(request, name);
    }

    public Integer[] getIntegerArray(String name, Integer[] defArray)
    {
        Integer[] ids = getIntegerArray(name);
        if (ArrayUtil.isEmpty(ids)) return defArray;
        return ids;
    }

    public Long[] getLongArray(String name, Long[] defArray) {
        Long[] ids = getLongArray(name);
        if (ArrayUtil.isEmpty(ids)) return defArray;
        return ids;
    }


    public Long[] getLongJoinArray(String name1, String name2)
    {
        Long[] ids1 = getLongArray(name1);
        Long[] ids2 = getLongArray(name2);
        return ArrayUtil.join(ids1,ids2);
    }

    public Long[] getLongArray(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (Long[])BeanUtil.getTypeValue(params.get(name),Long[].class);
            }
        }
        return RequestUtil.getLongArray(request, name);
    }

    public float[] getFloatArray(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (float[])BeanUtil.getTypeValue(params.get(name),float[].class);
            }
        }
        return RequestUtil.getFloatArray(request, name);
    }

    public double[] getDoubleArray(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (double[])BeanUtil.getTypeValue(params.get(name),double[].class);
            }
        }
        return RequestUtil.getDoubleArray(request, name);
    }

    public Float[] getFloatObjectArray(String name)
    {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (Float[])BeanUtil.getTypeValue(params.get(name),Float[].class);
            }
        }
        return RequestUtil.getFloatObjectArray(request, name);
    }

    public Double[] getDoubleObjectArray(String name)
    {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (Double[])BeanUtil.getTypeValue(params.get(name),Double[].class);
            }
        }
        return RequestUtil.getDoubleObjectArray(request, name);
    }

    public double getDouble(String name, double def) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return (double)BeanUtil.getTypeValue(params.get(name),double.class);
            }
        }
        return RequestUtil.getDouble(request, name, def);
    }


    public long getLong(String name) {
        return getLong(name, 0L);
    }

    public long getLong(String name, long def) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return params.getLong(name);
            }
        }
        return RequestUtil.getLong(request, name, def);
    }

    public float getFloat(String name, float def) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return params.getFloat(name);
            }
        }
        return RequestUtil.getFloat(request, name, def);
    }

    public boolean getBoolean(String name) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                return params.getBoolean(name);
            }
        }
        return RequestUtil.getBoolean(request, name);
    }

    public Date getDate(String name) {
        return getDate( name, null);
    }

    public Date getDate(String name, String format) {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                try {
                    return StringUtil.toDate(params.getString(name),format);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return RequestUtil.getDate(request, name, format, DateUtil.empty);
    }

    public String[] getParameterNames() throws Exception {
        if (environment.containsKey(Key_CallRocJsonData))
        {
            JSONObject params = getJsonParams();
            if (params!=null)
            {
                try {
                    return params.keySet().toArray(new String[0]);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return RequestUtil.getParameterNames(request);
    }

    public String[] getAttributeNames() throws Exception {
        return RequestUtil.getAttributeNames(request);
    }

    public boolean isMobileBrowser()
    {
       return RequestUtil.isMobileBrowser(request);
    }

    public boolean containsUserAgent(String str)
    {
        if (str==null) return false;
        String s = request.getHeader("User-Agent");
        return StringUtil.hasLength(s) && s.toLowerCase().contains(str.toLowerCase());
    }
    /**
     * @param name 参数
     * @return 满足ajax 请求转换,方便数组传递
     * @throws Exception
     */
    public String toQueryString(String name) {
        String[] array = getArray(name, false);
        StringBuilder sb = new StringBuilder();
        for (String value : array) {
            sb.append(name).append("=").append(URLUtil.getURLEncoder(value, Dispatcher.getEncode())).append("&");
        }
        if (sb.toString().endsWith("&")) sb.setLength(sb.length() - 1);
        return sb.toString();
    }

    /**
     * @param param 参数
     * @return 转换为参数格式
     * @throws Exception
     */
    public String toQueryString(Map<String, String> param) throws Exception {
        return RequestUtil.toQueryString(request, param);
    }

    public String getRemoteAddr()
    {
        return  RequestUtil.getRemoteAddr(request);
    }

    /**
     * 在拦截器里边放入如下代码就可以保存日志了
     * actionLog.setCaption(actionInvocation.getCaption());
     * actionLog.setClassMethod(operation);
     * actionLog.setMethodCaption(TXWebUtil.getMethodCaption(getClass(),operation));
     * actionLog.setNamespace(JUWebIoc.namespace);
     * actionLog.setPutName(userSession.getName());
     * actionLog.setPutUid(userSession.getUid());
     *
     * @return 得到一个已经初始化好的动作日志
     */
    public ActionLog getActionLog() {
        ActionLog actionLog = new ActionLog();
        long id = getLong("id");
        if (id == 0 && ClassUtil.isDeclaredMethod(getClass(), "getId")) {
            try {
                id = ObjectUtil.toLong(BeanUtil.getProperty(this, "getId"));
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        actionLog.setObjectId(id);
        actionLog.setClassName(getClass().getName());
        actionLog.setObjectType(StringUtil.substringBefore(getClass().getName(), "Action"));
        actionLog.setTitle(getActionLogTitle());
        Object logObject = getActionLogContent();
        if (logObject instanceof String) {
            actionLog.setContent((String) logObject);
        } else if (logObject instanceof Boolean || logObject instanceof StringBuilder || logObject instanceof StringBuffer || logObject instanceof Long || logObject instanceof Integer) {
            actionLog.setContent(logObject.toString());
        } else {
            actionLog.setContent(ScriptConverter.toXml(logObject));
        }
        actionLog.setActionResult(actionResult);
        actionLog.setIp(getRemoteAddr());
        return actionLog;

    }

    /**
     * @param level 级数
     * @return 得到路径
     */
    public String getPathLevel(int level) {
        level = level - 1;
        if (level < 0) level = 0;
        String url = request.getRequestURI();
        String[] paths = StringUtil.split(url, "/");
        if (paths.length >= level) {
            if (paths[level].endsWith("."+getEnv(Environment.filterSuffix)))
                return  FileUtil.getNamePart(paths[level]);
            return paths[level];
        }
        return StringUtil.empty;
    }

    public long getUrlNumber()
    {
        String actionName = getEnv(Key_ActionName);
        return StringUtil.toLong(StringUtil.getNumber(actionName));
    }
    /**
     * <input type="hidden" name="formHash" id="formHash" value="${action.formHash}" />
     * or
     * action.jsp?formHash=${action.formHash}
     *CSRF token
     * @return long type hashcode
     */
    @SuppressWarnings("unchecked")
    public String getFormHash()
    {
        if (session == null) return StringUtil.empty;
        //生成一个formhash,算法可以自己定，不随便重复就可以了
        //Key_FormHash
        //读取当前session里面的hashCode集合，此处使用了Set，方便判断。
        Set<String> formHashSession = (Set<String>) session.getAttribute(Key_FormHash);
        if (formHashSession == null) {
            formHashSession = new HashSet<String>();
        }
        if (formHashSession.size()>10) formHashSession.clear();
        String ulong = EncryptUtil.getMd5(session.getId()+System.currentTimeMillis());
        formHashSession.add(ulong);

        //保存
        session.setAttribute(Key_FormHash, formHashSession);
        put("formHash", ulong);
        return ulong;
    }

    /**
     * @return 判断是否重复提交
     */
    @SuppressWarnings("unchecked")
    public boolean isRepeatPost() {
        return isRepeatPost(null);
    }

    /**
     * @param formHash 检查数据
     * @return 判断是否重复提交
     */
    @SuppressWarnings("unchecked")
    public boolean isRepeatPost(String formHash)
    {
        if (!StringUtil.hasLength(formHash)) {
            try {
                formHash = getString(Key_FormHash);
            } catch (Exception e) {
                e.printStackTrace();
                return true;
            }
        }
        // 拿到session里面的集合
        Set<String> formHashSession = (Set<String>) session.getAttribute(Key_FormHash);
        // 如果没有，则是重复提交，或者非法提交
        if (formHashSession == null || !formHashSession.contains(formHash)) {
            return true;
        }
        formHashSession.remove(formHash);
        if (formHashSession.size() > 20) formHashSession.clear();
        return false;
    }

    /**
     * @return 文件真实执行的方法，而不是预执行的方法
     */
    public boolean isMethodInvoked() {
        return environment.containsKey(ActionSupport.Key_CallMethodName);
    }

    private String templatePath = null;

    public void setTemplatePath(String templatePath) {
        this.templatePath = templatePath;
    }

    /**
     * @return 返回模版文件路径部分
     */
    public String getTemplatePath() {
        if (StringUtil.isNULL(templatePath)) {
            StringBuilder sb = new StringBuilder();
            sb.append(Dispatcher.getRealPath());
            if (!TXWeb.global.equals(environment.get(Key_Namespace))) {
                sb.append("/").append((String) environment.get(Key_Namespace)).append("/");
            }
            return FileUtil.mendPath(sb.toString());
        }
        return templatePath;
    }

    /**
     * @return 返回模版文件的名称, 只有文件名称
     */
    public String getTemplateFile() {
        String actionName = getEnv(ActionSupport.Key_ActionName);
        if (StringUtil.isNULL(actionName)) return null;
        if (ObjectUtil.toBoolean(environment.get(KEY_MobileTemplate))&&isMobileBrowser())
        {
            return  actionName + StringUtil.DOT + mobileTemplateSuffix + StringUtil.DOT + getEnv(Environment.templateSuffix);
        }
        return actionName + StringUtil.DOT + getEnv(Environment.templateSuffix);
    }

    /**
     * @param name Cookie名称
     * @return 得到Cookie值
     */
    public String getCookie(String name) {
        return CookieUtil.getCookieString(request, name, StringUtil.empty);
    }

    public String getActionResult() {
        return actionResult;
    }

    /**
     * @param actionResult 放入 execute 返回标识
     */
    public void setActionResult(String actionResult) {
        this.actionResult = actionResult;
    }
    /**
     * 如果返回对象本身就是一个JSONObject 那么就直接返回这个返回对象
     *
     * @return 将提示信息转换为json 格式
     */
    @SuppressWarnings("unchecked")
    public JSONObject getRocResult() throws JSONException {
        Object result = environment.get(Key_ActionResultObject);
        if (result instanceof JSONObject)
        {
             JSONObject tmp = (JSONObject)result;
             if (!tmp.isEmpty())  return tmp;
        }

        JSONObject jsonObject = new JSONObject();
        if (hasFieldInfo())
        {
            jsonObject.put(Environment.id_success, YesNoType.NO);
            jsonObject.put(Environment.rocProtocol, Environment.jspxNetRoc);
            jsonObject.put(Environment.rocVersion, Environment.jspxNetRocVersion);
            jsonObject.put(Environment.rocId,getEnv(Key_ActionName));

            JSONObject errorJson = new JSONObject();
            jsonObject.put(Environment.id_error, errorJson);
            errorJson.put(Environment.id_errorCode, -320010);

            Map<String, String> fieldErrors = getFieldInfo();
            Iterator iterator = fieldErrors.values().iterator();
            if (iterator.hasNext()) {
                String msg = (String)iterator.next();
                errorJson.put(Environment.id_message, msg);
                jsonObject.put(Environment.id_message, msg);
            }
        } else if (hasActionMessage())
        {
            List<String> infoList = getActionMessage();
            Iterator iterator = infoList.iterator();
            if (iterator.hasNext())
            {
                String msg = (String)iterator.next();
                jsonObject.put(Environment.id_message, msg);
            }
            jsonObject.put(Environment.id_info_type, Environment.promptInfo);
            if (hasFieldInfo())
            {
                jsonObject.put(Environment.id_success, YesNoType.NO);
            } else {
                jsonObject.put(Environment.id_success, YesNoType.YES);
            }
            if (infoList.size()>1)
            {
                JSONArray message = new JSONArray();
                message.addAll(infoList);
                jsonObject.put(Environment.id_message_list, message);
            }
        }
        return jsonObject;
    }

    public void print(JSONObject json)
    {
        print(json,0);
    }

    public void print(JSONObject json,int status)
    {
        if (response==null)
        {
            System.out.println(json.toString(4));
        } else
          TXWebUtil.print(json.toString(4),TXWebUtil.jsonType,response,status);
    }

    public void print(String html)
    {
        print(html,-1);
    }

    public void print(String html,int status)
    {
        if (response==null)
        {
            System.out.println(html);
        } else
            TXWebUtil.print(html,TXWebUtil.htmlType,response,status);
    }

    public void printError(String html,int status)
    {
        if (response==null)
        {
            System.err.println(html);
        } else {
            try {
                TXWebUtil.errorPrint(html,response,status);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void printError(JSONObject json,int status)
    {
        if (response==null)
        {
            System.err.println(json.toString(4));
        } else
            TXWebUtil.print(json.toString(4),TXWebUtil.jsonType,response,status);
    }

    public IRole getRole()
    {
        IUserSession userSession = (IUserSession) getUserSession();
        if (userSession==null)
        {
            Role role = new Role();
            role.setId(0);
            role.setName(language.getLang(Environment.guestName));
            role.setUserType(UserType.NONE);
            role.setNamespace(getRootNamespace());
            return role;
        }
        return userSession.getRole(getRootNamespace());
    }

    /**
     * execute方法为默认执行必须执行， Operate 不生效
     *
     * @return 返回
     * @throws Exception 异常
     */
    public String execute() throws Exception {
        return actionResult;
    }
}